module Injector
    use Input
    implicit none

contains

    ! Injector Condition
    subroutine applyInjectorForParticle()
        implicit none

        ! Inject Ions
        if(xMinInjector .and. ppi==0)then
            call setPeriodicPosition_for_Injector(MPIInjectorListHeadRight)
            call moveListA2B(MPIInjectorListHeadRight,IonListHead)
        end if

        if(xMaxInjector .and. ppi==ppx-1)then
            call setPeriodicPosition_for_Injector(MPIInjectorListHeadLeft)
            call moveListA2B(MPIInjectorListHeadLeft,IonListHead)
        end if

        if(yMinInjector .and. ppj==0)then
            call setPeriodicPosition_for_Injector(MPIInjectorListHeadUp)
            call moveListA2B(MPIInjectorListHeadUp,IonListHead)
        end if

        if(yMaxInjector .and. ppj==ppy-1)then
            call setPeriodicPosition_for_Injector(MPIInjectorListHeadDown)
            call moveListA2B(MPIInjectorListHeadDown,IonListHead)
        end if
        call deleteList(MPIInjectorListHeadRight)
        call deleteList(MPIInjectorListHeadLeft)
        call deleteList(MPIInjectorListHeadUp)
        call deleteList(MPIInjectorListHeadDown)
        
    end subroutine applyInjectorForParticle

    subroutine setPeriodicPosition_for_Injector(ListHead)
        implicit none
        type(PseudoParticle), pointer :: ListHead
        type(PseudoParticle), pointer :: p, q

        if(associated(ListHead,MPIInjectorListHeadRight))then
            q => ListHead
            p => ListHead%next
            do while(associated(p))
                p%x = p%x+(xInjectMin-xInjectMax)
                q => p
                p => p%next
            end do
        end if

        if(associated(ListHead,MPIInjectorListHeadLeft))then
            q => ListHead
            p => ListHead%next
            do while(associated(p))
                p%x = p%x-(xInjectMin-xInjectMax)
                q => p
                p => p%next
            end do
        end if

        if(associated(ListHead,MPIInjectorListHeadUp))then
            q => ListHead
            p => ListHead%next
            do while(associated(p))
                p%y = p%y-(yInjectMax-yInjectMin)
                q => p
                p => p%next
            end do
        end if

        if(associated(ListHead,MPIInjectorListHeadDown))then
            q => ListHead
            p => ListHead%next
            do while(associated(p))
                p%y = p%y+(yInjectMax-yInjectMin)
                q => p
                p => p%next
            end do
        end if
    end subroutine setPeriodicPosition_for_Injector

    function isInjectorEmpty(i,j,Species)
        implicit none
        integer(kind=4) :: i, j, Species
        logical :: isInjectorEmpty
        type(FluidParticle) :: Injector
        real(kind=8) :: Sum

        Sum = 0.0d0
        call setInjectors(x(i,j),y(i,j),Species,Injector)
        Sum = Sum+Injector%ni
        call setInjectors(x(i+1,j),y(i+1,j),Species,Injector)
        Sum = Sum+Injector%ni
        call setInjectors(x(i,j+1),y(i,j+1),Species,Injector)
        Sum = Sum+Injector%ni
        call setInjectors(x(i+1,j+1),y(i+1,j+1),Species,Injector)
        Sum = Sum+Injector%ni

        if(Sum==0.0d0)then
            ! Cell is empty
            isInjectorEmpty = .true.
        else
            ! Cell is not empty
            isInjectorEmpty = .false.
        end if
    end function isInjectorEmpty

    subroutine createInjector(i,j,Species,PrevIon,ListHead)
        implicit none
        integer(kind=4) :: i, j, Species
        type(PseudoParticle), pointer :: PrevIon, ListHead
        type(PseudoParticle), pointer :: Ion
        type(FluidParticle) :: Injector
        real(kind=8) :: ThermalVelocity(3)
        real(kind=8) :: Position(2)
        real(kind=8) :: xCenter, yCenter
        integer(kind=4) :: m

        xCenter = 0.5d0*(x(i,j)+x(i+1,j))
        yCenter = 0.5d0*(y(i,j)+y(i,j+1))
        call setInjectors(xCenter,yCenter,Species,Injector)

        do m=1,Injector%ppc
            Position = getIonsPosition(i,j) ! Setup.F90
            call setInjectors(Position(1),Position(2),Species,Injector)

            if(Injector%ni>0.0d0)then
                allocate(Ion)
                Ion%Z = Injector%Z
                Ion%A = Injector%A
                Ion%x = Position(1)
                Ion%y = Position(2)

                ThermalVelocity = getMaxwell(Injector%A,Injector%Ti) ! Setup.F90
                Ion%vx = Injector%ux/v_unit+ThermalVelocity(1)*c/v_unit
                Ion%vy = Injector%uy/v_unit+ThermalVelocity(2)*c/v_unit
                Ion%vz = Injector%uz/v_unit+ThermalVelocity(3)*c/v_unit

                Ion%weight = Injector%ni/Injector%ppc/n_unit

                nullify(Ion%next)

                PrevIon%next => Ion
                PrevIon => PrevIon%next
            end if
        end do
    end subroutine createInjector
end module Injector